package com.ittx.dzt.jinglyun.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ittx.dzt.sys.util.json.JacksonTool;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.*;
import java.util.Map.Entry;

/**
 * 精确的签名字符串生成工具类
 * 严格遵循参数排序规则，正确处理数据类型格式
 */
public class JinglYunSignUtil {


	public static String joinParamsByMap(JSONObject jsonMap, String key) {
		if (jsonMap.containsKey("sign")) {
			jsonMap.remove("sign");
		}
		// 按字典序递归排序
		JSONObject sortedMap = sort(jsonMap);
		// 按URL键值对格式拼接
		StringBuilder builder = new StringBuilder();
		for (Map.Entry<String, Object> entry : sortedMap.entrySet()) {
			String k = entry.getKey();
			Object v = entry.getValue();
			// 参数值为null不参与签名
			if (v == null) {
				continue;
			}
			builder.append(k)
					.append("=")
					.append(v)
					.append("&");
		}
		// 将key拼接到字符串末尾
		builder.append("key=").append(key);
		return builder.toString();
	}

	public static String getSign(JSONObject jsonMap, String appSecret){
		// 生成签名
		String joinStr = joinParamsByMap(jsonMap, appSecret);
		return  md5UpperCase(joinStr);
	}

	private static JSONObject sort(JSONObject jsonObject) {
		// 内部使用TreeMap排序
		JSONObject sortedMap = new JSONObject(new TreeMap<>());
		// 遍历每一个属性
		for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
			String k = entry.getKey();
			Object v = entry.getValue();
			// 如果值是JSONObject或JSONArray类型，需要递归排序
			if (v instanceof JSONObject) {
				sortedMap.put(k, sort((JSONObject) v));
			} else if (v instanceof JSONArray) {
				sortedMap.put(k, sort((JSONArray) v));
			} else {
				sortedMap.put(k, v);
			}
		}
		return sortedMap;
	}

	private static JSONArray sort(JSONArray jsonArray) {
		// 空数组不需要排序
		int size = jsonArray.size();
		if (size == 0) {
			return jsonArray;
		}
		Object value = jsonArray.get(0);
		// 如果数组元素类型是JSONObject或JSONArray类型，数组内的每个元素递归排序
		if (value instanceof JSONObject) {
			for (int i = 0; i < size; i++) {
				jsonArray.set(i, sort(jsonArray.getJSONObject(i)));
			}
		} else if (value instanceof JSONArray) {
			for (int i = 0; i < size; i++) {
				jsonArray.set(i, sort(jsonArray.getJSONArray(i)));
			}
		}
		return jsonArray;
	}

	public static String md5UpperCase(String str) {
		return DigestUtils.md5Hex(str).toUpperCase();
	}

	/**
	 * 生成签名字符串
	 *
	 * @param params 参数映射（不包含sign参数）
	 * @return 排序后的签名字符串
	 */
	public static String generateSignString(Map<String, Object> params) {
		try {
			// 1. 参数过滤和预处理
			Map<String, Object> filteredParams = filterParams(params);

			// 2. 按参数名ASCII字典序排序并构建字符串
			return buildSortedString(filteredParams);

		} catch (Exception e) {
			throw new RuntimeException("生成签名字符串失败: " + e.getMessage(), e);
		}
	}

	/**
	 * 过滤参数：移除空值和sign参数
	 */
	private static Map<String, Object> filterParams(Map<String, Object> params) {
		Map<String, Object> filtered = new HashMap<>();

		for (Entry<String, Object> entry : params.entrySet()) {
			String key = entry.getKey();
			Object value = entry.getValue();

			// 跳过sign参数和空值
			if ("sign".equals(key) || value == null) {
				continue;
			}

			// 空字符串也不参与签名
			if (value instanceof String && ((String) value).isEmpty()) {
				continue;
			}

			filtered.put(key, value);
		}

		return filtered;
	}

	/**
	 * 构建排序后的参数字符串（核心修正方法）
	 */
	private static String buildSortedString(Map<String, Object> params) {
		// 使用TreeMap实现按key的ASCII字典序排序
		Map<String, Object> sortedParams = new TreeMap<>(params);
		StringBuilder sb = new StringBuilder();

		for (Entry<String, Object> entry : sortedParams.entrySet()) {
			String key = entry.getKey();
			Object value = entry.getValue();

			if (sb.length() > 0) {
				sb.append("&");
			}

			sb.append(key).append("=");

			// 处理不同类型的值
			if (value instanceof List) {
				// 处理列表类型（数组）
				sb.append(handleArrayValue((List<?>) value));
			} else if (value instanceof Map) {
				// 处理Map类型（JSON对象）
				sb.append(handleObjectValue((Map<String, Object>) value));
			} else {
				// 处理基本类型 - 关键修正：字符串值不加引号
				sb.append(handleBasicValue(value, false));
			}
		}

		return sb.toString();
	}

	/**
	 * 处理数组类型的值
	 */
	private static String handleArrayValue(List<?> array) {
		StringBuilder sb = new StringBuilder("[");

		for (int i = 0; i < array.size(); i++) {
			Object item = array.get(i);

			if (item instanceof Map) {
				// 数组中的JSON对象
				sb.append(handleObjectValue((Map<String, Object>) item));
			} else if (item instanceof List) {
				// 嵌套数组
				sb.append(handleArrayValue((List<?>) item));
			} else {
				// 数组中的基本类型 - 在数组内需要根据类型判断是否加引号
				sb.append(handleBasicValue(item, true));
			}

			if (i < array.size() - 1) {
				sb.append(",");
			}
		}

		sb.append("]");
		return sb.toString();
	}

	/**
	 * 处理对象类型的值（递归排序内部字段）
	 */
	private static String handleObjectValue(Map<String, Object> map) {
		// 使用TreeMap对内部字段也进行ASCII字典序排序
		Map<String, Object> sortedMap = new TreeMap<>(map);
		StringBuilder sb = new StringBuilder("{");

		int index = 0;
		for (Entry<String, Object> entry : sortedMap.entrySet()) {
			String key = entry.getKey();
			Object value = entry.getValue();

			if (index > 0) {
				sb.append(",");
			}

			// JSON键必须加引号
			sb.append("\"").append(key).append("\":");

			if (value instanceof Map) {
				sb.append(handleObjectValue((Map<String, Object>) value));
			} else if (value instanceof List) {
				sb.append(handleArrayValue((List<?>) value));
			} else {
				// JSON对象内的值需要根据类型判断是否加引号
				sb.append(handleBasicValue(value, true));
			}

			index++;
		}

		sb.append("}");
		return sb.toString();
	}

	/**
	 * 处理基本类型的值（关键修正方法）
	 *
	 * @param value         值
	 * @param inJsonContext 是否在JSON上下文内（数组或对象中）
	 * @return 格式化后的字符串
	 */
	private static String handleBasicValue(Object value, boolean inJsonContext) {
		if (value instanceof String) {
			System.out.println("value:"+value);
			// 关键修正：只有在JSON上下文内（数组或对象中）的字符串才加引号
			if (inJsonContext) {
				return "\"" + value + "\"";
			} else {
				// 顶级参数值的字符串不加引号
				return value.toString();
			}
		} else if (value instanceof Number) {
			// 数字类型永远不加引号
			return value.toString();
		} else if (value instanceof Boolean) {
			return value.toString();
		} else {
			return String.valueOf(value);
		}
	}

	/**
	 * 完整的签名生成方法（包含MD5加密）
	 */
	public static String generateSignature(Map<String, Object> params, String secretKey) {
		String signString = generateSignString(params);
		String stringSignTemp = signString + "&key=" + secretKey;
		System.out.println("签名字符串："+stringSignTemp);
		return generateMD5(stringSignTemp).toUpperCase();
	}

	/**
	 * 生成MD5哈希
	 */
	private static String generateMD5(String input) {
		try {
			java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
			byte[] digest = md.digest(input.getBytes("UTF-8"));

			StringBuilder hexString = new StringBuilder();
			for (byte b : digest) {
				String hex = Integer.toHexString(0xff & b);
				if (hex.length() == 1) {
					hexString.append('0');
				}
				hexString.append(hex);
			}
			return hexString.toString();
		} catch (Exception e) {
			throw new RuntimeException("MD5加密失败", e);
		}
	}

	// public static void main(String[] args) {
	// 	// 构建测试数据（基于您提供的参数）
	// 	Map<String, Object> params = new HashMap<>();
	// 	params.put("appId", "jingLingSupplier");
	// 	params.put("supplierDockId", "9297d8e86af74b5ba8040119a4d26bb0");
	// 	params.put("gmtRequest", System.currentTimeMillis());
	// 	params.put("randomStr", "randomString");
	//
	// 	// 字符串数组
	// 	params.put("lstStr", Arrays.asList("3", "2", "1"));
	//
	// 	// 整数数组（注意：数字不加引号）
	// 	params.put("lstInt", Arrays.asList(3, 2, 1));
	//
	// 	// 构建嵌套的deliveryDetails数组
	// 	List<Map<String, Object>> deliveryDetails = new ArrayList<>();
	// 	Map<String, Object> detail = new HashMap<>();
	// 	detail.put("skuId", 45632452);
	// 	detail.put("b3skuId", "b3");
	// 	detail.put("itemNum", 1);  // itemNum会排在skuId前面（ASCII字典序）
	// 	detail.put("aSkuId", 1);
	// 	detail.put("a1SkuId", "a1");
	// 	deliveryDetails.add(detail);
	// 	params.put("deliveryDetails", deliveryDetails);
	//
	//
	// 	System.out.println("签名参数：" + JacksonTool.toJson(params));
	// 	// 生成签名字符串
	// 	String signString = generateSignString(params);
	// 	System.out.println("生成的签名字符串: " + signString);
	//
	// 	// 预期结果对比
	// 	String expected = "appId=jingLingSupplier&deliveryDetails=[{\"itemNum\":1,\"skuId\":45632452}]&gmtRequest=1760685808276&lstInt=[3,2,1]&lstStr=[\"3\",\"2\",\"1\"]&randomStr=randomString&supplierDockId=9297d8e86af74b5ba8040119a4d26bb0";
	//
	// 	System.out.println("预期签名字符串: " + expected);
	// 	System.out.println("匹配结果: " + signString.equals(expected));
	//
	// 	// 如果需要生成完整签名（包含MD5加密）
	// 	String secretKey = "your_secret_key";
	// 	String signature = generateSignature(params, secretKey);
	// 	System.out.println("完整签名: " + signature);
	// }
	public static void main(String[] args) {
		// 构建测试数据（基于您提供的参数）
		Map<String, Object> params = new HashMap<>();
		params.put("appId", "ittxSupplier");
		params.put("supplierDockId", "3264bfcccc904f9b9298b49d4b6f8f5a");
		params.put("gmtRequest", System.currentTimeMillis());
		params.put("randomStr", "randomString");

		List<Map<String, String>> decryptionReqList = new ArrayList<>();
		// Map<String, String> decryptMap = new HashMap<>();
		// decryptMap.put("deSensitiveText", "徐**");
		// decryptMap.put("ciphertext", "3ahbs1Z92neqUvDPbem1JwaiwnCDuFuUCGdgbvAUw2AKjEFuRcCrlPc+EQwNgClk");
		// decryptionReqList.add(decryptMap);

		Map<String, String> decryptMap1 = new HashMap<>();
		decryptMap1.put("deSensitiveText", "***********");
		// decryptMap1.put("ciphertext", "m+mO++MY/qe/EWU/kHnSAYtsp99CAl7XCE/TS+UHEqCZVuhuDo86O5qboYBggVhPQ/L5ppmDYUdU\\nmeTioS8YCIIupJ/RySTkbov338SqFGk=");
		decryptMap1.put("ciphertext", "m+mO++MY/qe/EWU/kHnSAYtsp99CAl7XCE/TS+UHEqCZVuhuDo86O5qboYBggVhPQ/L5ppmDYUdU\nmeTioS8YCIIupJ/RySTkbov338SqFGk=");
		decryptionReqList.add(decryptMap1);

		params.put("decryptionReqList", decryptionReqList);

		System.out.println("签名参数：" + JacksonTool.toJson(params));
		// appId=ittxSupplier&decryptionReqList=[{"ciphertext":"m+mO++MY/qe/EWU/kHnSAYtsp99CAl7XCE/TS+UHEqCZVuhuDo86O5qboYBggVhPQ/L5ppmDYUdU\nmeTioS8YCIIupJ/RySTkbov338SqFGk=","deSensitiveText":"***********"}]&gmtRequest=1762329669979&randomStr=randomString&supplierDockId=3264bfcccc904f9b9298b49d4b6f8f5a&key=ECF6CE118870492BBB4CE03E1CBA0B99
		// 如果需要生成完整签名（包含MD5加密）
		String secretKey = "ECF6CE118870492BBB4CE03E1CBA0B99";
		// String signature = generateSignature(params, secretKey);
		// System.out.println("完整签名: " + signature);
		// params.put("sign", signature);
		// System.out.println("请求参数：" + JacksonTool.toJson(params));



		// System.out.println("签名参数：" + JacksonTool.toJson(params));
		String signature = getSign(JSON.parseObject(JacksonTool.toJson(params)), secretKey);
		System.out.println("sign:"+ signature);

		params.put("sign", signature);
		System.out.println("请求参数：" + JacksonTool.toJson(params));

	}
}